// ----------------------------------
// RSDK Project: Sonic 2
// Script Description: Transporter Object
// Script Author: Christian Whitehead/Simon Thomley
// Unpacked by Rubberduckycooly's script unpacker
// ----------------------------------

// ========================
// Aliases
// ========================

private alias object.value0 : object.playerID
private alias object.value1 : object.nodePos.x
private alias object.value2 : object.nodePos.y
private alias object.value3 : object.nodeChangeDelay
private alias object.value4 : object.tablePtr
private alias object.value5 : object.tableSize
private alias object.value6 : object.tablePos
private alias object.value7 : object.parent
private alias object.value8 : object.activePlayers

// States
private alias 0 : TRANSPORTER_WAITING
private alias 1 : TRANSPORTER_ACTIVATING
private alias 2 : TRANSPORTER_TRANSPORTING

// Types
private alias 0  : TRANSPORTER_TYPE_LDR
private alias 1  : TRANSPORTER_TYPE_R
private alias 2  : TRANSPORTER_TYPE_LDR_2
private alias 3  : TRANSPORTER_TYPE_3
private alias 4  : TRANSPORTER_TYPE_4
private alias 5  : TRANSPORTER_TYPE_RUL
private alias 6  : TRANSPORTER_TYPE_LUR
private alias 7  : TRANSPORTER_TYPE_RUL_1
private alias 8  : TRANSPORTER_TYPE_RDL
private alias 9  : TRANSPORTER_TYPE_9
private alias 10 : TRANSPORTER_TYPE_R0
private alias 11 : TRANSPORTER_TYPE_LUR_2
private alias 12 : TRANSPORTER_TYPE_RUL_2

// Player Aliases
private alias object.state : player.state
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos
private alias object.xvel : player.xvel
private alias object.yvel : player.yvel
private alias object.speed : player.speed
private alias object.gravity : player.gravity
private alias object.animationSpeed : player.animationSpeed
private alias object.animation : player.animation
private alias object.interaction : player.interaction
private alias object.scrollTracking : player.scrollTracking
private alias object.tileCollisions : player.tileCollisions

private alias object.value5  : player.rollAnimationSpeed
private alias object.value7  : player.invincibleTimer


// ========================
// Function Declarations
// ========================

reserve function Transporter_HandleNewNode


// ========================
// Tables
// ========================

private table Transporter_tableSizes
	6, 2, 6, 2, 2, 6, 6, 6, 6, 6, 6, 6, 6
end table

private table Transporter_frameTable
	1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0
end table

private table Transporter_tablePtrs[13]

private table Transporter_movementTable0
	0x7A80000, 0x2700000, 0x7500000, 0x2700000, 0x7400000, 0x2800000, 0x7400000, 0x3E00000, 0x7500000, 0x3F00000, 0x7A80000, 0x3F00000
end table

private table Transporter_movementTable1
	0xC580000, 0x5F00000, 0xE280000, 0x5F00000
end table

private table Transporter_movementTable2
	0x18280000, 0x6B00000, 0x17D00000, 0x6B00000, 0x17C00000, 0x6C00000, 0x17C00000, 0x7E00000, 0x17B00000, 0x7F00000, 0x17580000, 0x7F00000
end table

private table Transporter_movementTable3
	0x5D80000, 0x3700000, 0x7800000, 0x3700000
end table

private table Transporter_movementTable4
	0x5D80000, 0x5F00000, 0x7000000, 0x5F00000
end table

private table Transporter_movementTable5
	0xBD80000, 0x1F00000, 0xC300000, 0x1F00000, 0xC400000, 0x1E00000, 0xC400000, 0xC00000, 0xC500000, 0xB00000, 0xCA80000, 0xB00000
end table

private table Transporter_movementTable6
	0x17280000, 0x3300000, 0x15D00000, 0x3300000, 0x15C00000, 0x3200000, 0x15C00000, 0x2400000, 0x15D00000, 0x2300000, 0x16280000, 0x2300000
end table

private table Transporter_movementTable7
	0x6D80000, 0x1F00000, 0x7300000, 0x1F00000, 0x7400000, 0x1E00000, 0x7400000, 0x1000000, 0x7500000, 0xF00000, 0x7A80000, 0xF00000
end table

private table Transporter_movementTable8
	0x7D80000, 0x3300000, 0x8280000, 0x3300000, 0x8400000, 0x3400000, 0x8400000, 0x4580000, 0x8280000, 0x4700000, 0x7D80000, 0x4700000
end table

private table Transporter_movementTable9
	0xFD80000, 0x3B00000, 0x10280000, 0x3B00000, 0x10400000, 0x3980000, 0x10400000, 0x2C40000, 0x10580000, 0x2B00000, 0x10A80000, 0x2B00000
end table

private table Transporter_movementTable10
	0xFD80000, 0x4B00000, 0x10280000, 0x4B00000, 0x10400000, 0x4C00000, 0x10400000, 0x5D80000, 0x10580000, 0x5F00000, 0x10A80000, 0x5F00000
end table

private table Transporter_movementTable11
	0x20580000, 0x4300000, 0x20A80000, 0x4300000, 0x20C00000, 0x4180000, 0x20C00000, 0x2C00000, 0x20D00000, 0x2B00000, 0x21280000, 0x2B00000
end table

private table Transporter_movementTable12
	0x23280000, 0x5B00000, 0x22D00000, 0x5B00000, 0x22C00000, 0x5A00000, 0x22C00000, 0x4C00000, 0x22D00000, 0x4B00000, 0x23280000, 0x4B00000
end table

private table Transporter_movementTableCD
	0x55850000, 0x5B00000, 0x22D00000, 0x5B00000, 0x22C00000, 0x5A00000, 0x22C00000, 0x4C00000, 0x22D00000, 0x4B00000, 0x60140000, 0x4B00000
end table

// ========================
// Function Definitions
// ========================

private function Transporter_HandleNewNode
	temp0 = object.nodePos.x
	temp2 = 0x1000
	temp0 -= player[currentPlayer].xpos
	if temp0 < 0
		FlipSign(temp0)
		FlipSign(temp2)
	end if
	temp0 >>= 16

	temp1 = object.nodePos.y
	temp3 = 0x1000
	temp1 -= player[currentPlayer].ypos
	if temp1 < 0
		FlipSign(temp1)
		FlipSign(temp3)
	end if
	temp1 >>= 16

	if temp1 >= temp0
		temp1 = object.nodePos.y
		temp1 -= player[currentPlayer].ypos
		temp1 &= 0xFFFF0000
		temp1 /= temp3
		temp0 = object.nodePos.x
		temp0 -= player[currentPlayer].xpos
		if temp0 != 0
			temp0 &= 0xFFFF0000
#platform: USE_STANDALONE
			temp0 /= temp1
#endplatform
#platform: USE_ORIGINS
			if temp1 != 0
				temp0 /= temp1
			end if
#endplatform
		end if
		temp0 <<= 8
		temp3 <<= 8
		temp1 >>= 8
		player[currentPlayer].xvel = temp0
		player[currentPlayer].yvel = temp3
		Abs(temp1)
		object.nodeChangeDelay = temp1
	else
		temp0 = object.nodePos.x
		temp0 -= player[currentPlayer].xpos
		temp0 &= 0xFFFF0000
		temp0 /= temp2
		temp1 = object.nodePos.y
		temp1 -= player[currentPlayer].ypos
		if temp1 != 0
			temp1 &= 0xFFFF0000
#platform: USE_STANDALONE
			temp1 /= temp0
#endplatform
#platform: USE_ORIGINS
			if temp0 != 0
				temp1 /= temp0
			end if
#endplatform
		end if
		temp1 <<= 8
		temp2 <<= 8
		temp0 >>= 8
		player[currentPlayer].xvel = temp2
		player[currentPlayer].yvel = temp1
		Abs(temp0)
		object.nodeChangeDelay = temp0
	end if
end function


// ========================
// Events
// ========================

event ObjectUpdate
	switch object.state
	case TRANSPORTER_WAITING
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
#platform: USE_ORIGINS
			temp3 = 1
			temp3 <<= currentPlayer
			temp4 = temp3
			temp4 &= object.activePlayers
			if temp4 == false
#endplatform
				if player[currentPlayer].state != Player_State_Static
					temp0 = player[currentPlayer].xpos
					temp0 -= object.xpos
					temp0 += 0x30000
					if object.direction == FLIP_X
						temp0 += 0xA0000
					end if

					if temp0 >= 0
						if temp0 < 0x100000
							temp1 = player[currentPlayer].ypos
							temp1 -= object.ypos
							temp1 += 0x200000
							if temp1 >= 0
								if temp1 < 0x400000
									temp0 = object.propertyValue
									temp0 &= 15
									CreateTempObject(TypeName[Transporter], object.propertyValue, object.xpos, object.ypos)
									GetTableValue(object[tempObjectPos].tablePtr, temp0, Transporter_tablePtrs)
									GetTableValue(object[tempObjectPos].tableSize, temp0, Transporter_tableSizes)
									GetTableValue(temp1, 0, object[tempObjectPos].tablePtr)
									GetTableValue(temp2, 2, object[tempObjectPos].tablePtr)
									if temp2 > temp1
										object[tempObjectPos].direction = FLIP_X
									end if
									object[tempObjectPos].state  	= TRANSPORTER_ACTIVATING
									object[tempObjectPos].playerID 	= currentPlayer

									player[currentPlayer].state 				= Player_State_Static
									player[currentPlayer].interaction 			= false
									player[currentPlayer].tileCollisions 		= false
									player[currentPlayer].animation 			= ANI_JUMPING
									player[currentPlayer].rollAnimationSpeed 	= 0
									player[currentPlayer].animationSpeed 		= 0
									player[currentPlayer].xvel 					= 0
									player[currentPlayer].yvel 					= 0
									player[currentPlayer].gravity 				= 1
									player[currentPlayer].scrollTracking 		= true
									player[currentPlayer].xpos 					= object.xpos
									player[currentPlayer].ypos 					= object.ypos
									PlaySfx(SfxName[Rolling], false)
									
#platform: USE_ORIGINS
									object.activePlayers |= temp3
									object[tempObjectPos].parent = object.entityPos
#endplatform
								end if
							end if
						end if
					end if
				end if
#platform: USE_ORIGINS
			end if
#endplatform
		next
		break

	case TRANSPORTER_ACTIVATING
		currentPlayer = object.playerID
		Sin256(player[currentPlayer].ypos, object.angle)
		object.angle += 2

		player[currentPlayer].ypos <<= 11
		FlipSign(player[currentPlayer].ypos)
		player[currentPlayer].ypos += object.ypos
		if player[currentPlayer].invincibleTimer < 2
			player[currentPlayer].invincibleTimer = 2
		end if

		if object.angle == 0x80
			temp0 = object.tablePos
			temp0 <<= 1
			GetTableValue(object.nodePos.x, temp0, object.tablePtr)
			temp0++
			GetTableValue(object.nodePos.y, temp0, object.tablePtr)
			CallFunction(Transporter_HandleNewNode)
			object.state++
			object.frame = 0
			PlaySfx(SfxName[Release], false)
		end if
		break

	case TRANSPORTER_TRANSPORTING
		currentPlayer = object.playerID
		object.nodeChangeDelay--
		if object.nodeChangeDelay < 0
			player[currentPlayer].xpos = object.nodePos.x
			player[currentPlayer].ypos = object.nodePos.y
			object.tablePos++
			if object.tablePos >= object.tableSize
				object.type = TypeName[Blank Object]
				
#platform: USE_ORIGINS
				temp1 = 1
				temp1 <<= currentPlayer
				arrayPos0 = object.parent
				object[arrayPos0].activePlayers ^= temp1
#endplatform
				
				player[currentPlayer].ypos &= 0x7FF0000
				player[currentPlayer].interaction 		= true
				player[currentPlayer].tileCollisions 	= true

				GetBit(temp1, object.propertyValue, 4)
				if temp1 == false
					player[currentPlayer].xvel 		= 0
					player[currentPlayer].yvel 		= 0x20000
					player[currentPlayer].speed 	= 0
					player[currentPlayer].animation = ANI_WALKING
#platform: USE_STANDALONE
					player[currentPlayer].state		= Player_State_Air
#endplatform
#platform: USE_ORIGINS
					player[currentPlayer].state		= Player_State_Air_NoDropDash
#endplatform
				else
					player[currentPlayer].xvel 	= 0x100000
					player[currentPlayer].speed = 0x100000
					player[currentPlayer].state = Player_State_Ground
				end if
			else
				temp0 = object.tablePos
				temp0 <<= 1
				GetTableValue(object.nodePos.x, temp0, object.tablePtr)
				temp0++
				GetTableValue(object.nodePos.y, temp0, object.tablePtr)
				CallFunction(Transporter_HandleNewNode)
			end if
		end if
		break
		
	end switch

	if object.state >= TRANSPORTER_ACTIVATING
		temp0 = object.animationTimer
		temp0 >>= 1
		GetTableValue(object.frame, temp0, Transporter_frameTable)
		object.animationTimer++
		if object.animationTimer == 30
			object.animationTimer = 26
		end if
	end if
end event


event ObjectDraw
	DrawSpriteFX(object.frame, FX_FLIP, object.xpos, object.ypos)
end event


event ObjectStartup
	LoadSpriteSheet("MPZ/Objects.gif")
	SpriteFrame(0, 0, 1, 1, 1, 1)
	SpriteFrame(-8, -24, 28, 40, 0, 29)

	SetTableValue(Transporter_movementTable0, TRANSPORTER_TYPE_LDR, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable1, TRANSPORTER_TYPE_R, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable2, TRANSPORTER_TYPE_LDR_2, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable3, TRANSPORTER_TYPE_3, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable4, TRANSPORTER_TYPE_4, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable5, TRANSPORTER_TYPE_RUL, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable6, TRANSPORTER_TYPE_LUR, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable7, TRANSPORTER_TYPE_RUL_1, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable8, TRANSPORTER_TYPE_RDL, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable9, TRANSPORTER_TYPE_9, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable10, TRANSPORTER_TYPE_R0, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable11, TRANSPORTER_TYPE_LUR_2, Transporter_tablePtrs)
	SetTableValue(Transporter_movementTable12, TRANSPORTER_TYPE_RUL_2, Transporter_tablePtrs)
end event


// ========================
// Editor Events
// ========================

event RSDKEdit
	if editor.returnVariable == true
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			checkResult = object.propertyValue
			break
			
		case 0 // type
			checkResult = object.propertyValue
			checkResult &= 15
			break
			
		case 1 // exitType
			GetBit(checkResult, object.propertyValue, 4)
			break
			
		end switch
	else
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			object.propertyValue = editor.variableValue
			break
			
		case 0 // type
			object.propertyValue &= 240
			editor.variableValue &= 15
			
			object.propertyValue |= editor.variableValue
			break
			
		case 1 // exitType
			CheckNotEqual(editor.variableValue, false)
			SetBit(object.propertyValue, 4, checkResult)
			break
			
		end switch
	end if
end event


event RSDKDraw
	DrawSprite(0)
end event


event RSDKLoad
	LoadSpriteSheet("Global/Display.gif")
	SpriteFrame(-8, -8, 16, 16, 168, 18) // "trigger" - #0

	AddEditorVariable("type")
	SetActiveVariable("type")
	AddEnumVariable("Left, Down, Right", TRANSPORTER_TYPE_LDR)
	AddEnumVariable("Right", TRANSPORTER_TYPE_R)
	AddEnumVariable("Left, Down, Right (Alt)", TRANSPORTER_TYPE_LDR_2)
	AddEnumVariable("Type 3", TRANSPORTER_TYPE_3)
	AddEnumVariable("Type 4", TRANSPORTER_TYPE_4)
	AddEnumVariable("Right, Up, Left", TRANSPORTER_TYPE_RUL)
	AddEnumVariable("Left (Long), Up, Right", TRANSPORTER_TYPE_LUR)
	AddEnumVariable("Right, Up, Left (Alt 1)", TRANSPORTER_TYPE_RUL_1)
	AddEnumVariable("Right, Down, Left", TRANSPORTER_TYPE_RDL)
	AddEnumVariable("Type9", TRANSPORTER_TYPE_9)
	AddEnumVariable("Type10", TRANSPORTER_TYPE_R0)
	AddEnumVariable("Left, Up, Right", TRANSPORTER_TYPE_LUR_2)
	AddEnumVariable("Right, Up, Left (Alt 2)", TRANSPORTER_TYPE_RUL_2)

	AddEditorVariable("exitType")
	SetActiveVariable("exitType")
	AddEnumVariable("Transporter Exit", 0)
	AddEnumVariable("Shoot Out From Exit", 1)
end event
